Code
import requests
import pandas as pd
import geopandasOpenSky provides api to get data for flights in progress. It is rate limited
import requests
import pandas as pd
import geopandasdef fetch_opensky_data():
url = "https://opensky-network.org/api/states/all"
response = requests.get(url)
data = response.json()
columns = [
"icao24", "callsign", "origin_country", "time_position", "last_contact",
"longitude", "latitude", "baro_altitude", "on_ground", "velocity",
"heading", "vertical_rate", "sensors", "geo_altitude", "squawk",
"spi", "position_source"
]
df_raw = pd.DataFrame(data['states'], columns=columns)
return (
df_raw
.assign(
time_position=pd.to_datetime(df_raw["time_position"], unit="s"),
last_contact=pd.to_datetime(df_raw["last_contact"], unit="s"),
)
)
df_flights = fetch_opensky_data()
df_flihts_non_nan = df_flights.dropna(subset=["longitude", "latitude"])
gdf = geopandas.GeoDataFrame(
df_flihts_non_nan,
geometry=geopandas.points_from_xy(df_flihts_non_nan.longitude, df_flihts_non_nan.latitude),
crs="EPSG:4326",
)
gdf.explore(fullscreen=True, tooltip=False, popup=True)Flights in world at notebook time
(
df_flights
.groupby("origin_country")
.agg(num_flights=("icao24", "count"))
.sort_values("num_flights", ascending=False)
.head(20)
)| num_flights | |
|---|---|
| origin_country | |
| United States | 5932 |
| Canada | 436 |
| United Kingdom | 361 |
| Australia | 260 |
| Ireland | 230 |
| Brazil | 124 |
| Turkey | 124 |
| Germany | 107 |
| Spain | 106 |
| China | 98 |
| Malta | 94 |
| United Arab Emirates | 83 |
| Austria | 80 |
| India | 71 |
| Kingdom of the Netherlands | 70 |
| France | 67 |
| Mexico | 66 |
| Republic of Korea | 66 |
| New Zealand | 64 |
| Japan | 63 |
Top 20 countries with most flights
For reference
df_flights| icao24 | callsign | origin_country | time_position | last_contact | longitude | latitude | baro_altitude | on_ground | velocity | heading | vertical_rate | sensors | geo_altitude | squawk | spi | position_source | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | e8027c | LPE2338 | Chile | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -79.1481 | -8.7767 | 9136.38 | False | 219.94 | 333.32 | 0.00 | None | 9784.08 | None | False | 0 |
| 1 | a3feec | N357BE | United States | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -97.3697 | 41.8808 | 12496.80 | False | 213.29 | 161.00 | 0.33 | None | 12710.16 | 2455 | False | 0 |
| 2 | 39de4d | TVF31HD | France | 2025-05-28 21:45:25 | 2025-05-28 21:45:25 | -5.8982 | 37.4228 | NaN | True | 2.57 | 317.81 | NaN | None | NaN | 7621 | False | 0 |
| 3 | a5953a | TRF559 | United States | 2025-05-28 21:47:17 | 2025-05-28 21:47:20 | -96.2515 | 33.0461 | 205.74 | False | 30.97 | 138.37 | -2.93 | None | 213.36 | 1200 | False | 0 |
| 4 | a5f84e | N484JS | United States | 2025-05-28 21:46:04 | 2025-05-28 21:46:04 | -98.6936 | 29.7275 | NaN | True | 0.39 | 92.81 | NaN | None | NaN | None | False | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 9356 | a4359b | UPS5804 | United States | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -100.8087 | 41.3746 | 10370.82 | False | 192.56 | 267.70 | 0.00 | None | 10607.04 | 3454 | False | 0 |
| 9357 | abc0e4 | SWA2446 | United States | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -90.2898 | 38.5997 | 1097.28 | False | 138.81 | 107.02 | -2.28 | None | 1127.76 | 3631 | False | 0 |
| 9358 | 4b1901 | EDW10 | Switzerland | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -115.5372 | 54.1183 | 11582.40 | False | 223.59 | 220.80 | 0.00 | None | 12009.12 | None | False | 0 |
| 9359 | 4caa32 | ITY629 | Ireland | 2025-05-28 21:48:06 | 2025-05-28 21:48:06 | -79.5480 | 43.5888 | 11277.60 | False | 258.09 | 65.63 | 0.00 | None | 11551.92 | 5771 | False | 0 |
| 9360 | c00734 | WJA1611 | Canada | 2025-05-28 21:48:05 | 2025-05-28 21:48:05 | -105.2619 | 48.9154 | 11590.02 | False | 248.25 | 282.57 | 0.00 | None | 11910.06 | None | False | 0 |
9361 rows × 17 columns